from rest_framework import serializers
from .models import User
import re
from django_redis import get_redis_connection
from rest_framework_jwt.settings import api_settings

from celery_tasks.email.tasks import send_verify_email

'''创建用户序列化器'''


class UserCreateSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    # 用户名
    username = serializers.CharField(
        min_length=5,
        max_length=20,
        error_messages={
            'min_length': '用户名不能少于5个字',
            'max_length': '用户名不能大于20个字'
        }
    )

    # 手机号
    mobile = serializers.CharField()
    # 密码
    password = serializers.CharField(
        write_only=True,
        min_length=8,
        max_length=20,
        error_messages={
            'min_length': '密码长度不能小于8个字符',
            'max_length': '密码长度不能大于20个字符'
        }
    )
    # 确认密码
    password2 = serializers.CharField(
        write_only=True,
        min_length=8,
        max_length=20,
        error_messages={
            'min_length': '密码长度不能小于8个字符',
            'max_length': '密码长度不能大于20个字符'
        }
    )

    # 是否同意协议
    allow = serializers.CharField(write_only=True)
    # 短信验证码
    sms_code = serializers.CharField(write_only=True)

    token = serializers.CharField(label='登陆状态token', read_only=True)

    '''验证单个属性'''

    # 验证用户名是否存在
    def validate_username(self, value):
        count = User.objects.filter(username=value).count()

        if not re.search(r'[a-zA-Z]', value):
            raise serializers.ValidationError(
                '用户名必须包含字母'
            )

        if count > 0:
            raise serializers.ValidationError(
                '用户名以存在'
            )
        print(value)
        return value

    # 验证手机号是否存在
    def validate_mobile(self, value):
        # 验证手机号格式
        if not re.match(r"^1[3-9]\d{9}$", value):
            raise serializers.ValidationError(
                '手机号格式错误'
            )
            # 手机号是否存在

        count = User.objects.filter(mobile=value).count()
        if count > 0:
            raise serializers.ValidationError(
                '手机号以存在'
            )
        return value

    # 验证短信验证码格式
    def validate_sms_code(self, value):
        if not re.match(r'^\d{6}$', value):
            raise serializers.ValidationError(
                '验证码格式错误'
            )
        return value

    # 验证是否同意协议
    def validate_allow(self, value):
        if not value:
            raise serializers.ValidationError(
                '请同意协议'
            )
        return value

    '''验证多个属性'''

    def validate(self, attrs):
        # 验证两次密码是否一致
        password = attrs.get('password')
        password2 = attrs.get('password2')

        if password != password2:
            raise serializers.ValidationError(
                '两次密码不一致'
            )
        # 判断短信验证码是否正确
        # 创建从redis获取验证码的对象
        redis_cli = get_redis_connection('verify_code')
        # 接收手机号的键
        key = 'sms_code_' + attrs.get('mobile')
        # 从redis中通过键获取短信验证码的值
        sms_code_redis = redis_cli.get(key)
        # 接收用户输入的验证码
        sms_code_request = attrs.get('sms_code')
        # 如果redis中没有键
        if not sms_code_redis:
            raise serializers.ValidationError(
                '验证码已经过期'
            )
        # 强制删除
        redis_cli.delete(key)

        if sms_code_redis.decode() != sms_code_request:
            raise serializers.ValidationError(
                '短信验证码错误'
            )
        # 所有验证通过返回
        return attrs

    # 重写create方法把注册信息添加到数据库

    def create(self, validated_data):
        user = User()
        user.username = validated_data.get('username')
        user.mobile = validated_data.get('mobile')
        user.set_password(validated_data.get('password'))
        user.save()

        '''增生代码：生成记录登陆状态的token'''

        jwt_paload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_paload_handler(user)
        token = jwt_encode_handler(payload)
        user.token = token

        return user


class UserDetailSerializer(serializers.ModelSerializer):
    """
    用户详细信息序列化器
    """

    class Meta:
        model = User
        fields = ('id', 'username', 'mobile', 'email', 'email_active')


class EmailSerializer(serializers.ModelSerializer):
    """
    邮箱序列化器
    """

    class Meta:
        model = User
        fields = ('id', 'email')
        extra_kwargs = {
            'email': {
                'required': True
            }
        }

    def update(self, instance, validated_data):
        email = validated_data['email']
        instance.email = validated_data['email']
        instance.save()

        # 生成验证链接
        verify_url = instance.generate_verify_email_url()
        # 发送验证邮件
        send_verify_email.delay(email, verify_url)

        return instance